package com.flower.interceptor;

import com.flower.properties.JwtProperties;
import com.flower.utils.JwtUtil;
import com.flower.utils.UserContext;
import io.jsonwebtoken.Claims;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.lang.NonNull;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import com.flower.exception.LoginException;
/*
 * jwt令牌校验的拦截器

 */


@Component
@Slf4j
public class JwtTokenInterceptor implements HandlerInterceptor {
    @Autowired
    private JwtProperties jwtProperties;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    /**
     * 校验JWT令牌
     *
     * @param request  请求对象
     * @param response 响应对象
     * @param handler  处理对象
     * @return 是否允许请求继续
     * @throws Exception 异常处理
     */

    @Override
    public boolean preHandle(@NonNull HttpServletRequest request, @NonNull HttpServletResponse response, @NonNull Object handler) {
        String token = request.getHeader("Authorization");
        String frontendType = request.getHeader("Frontend-Type");
        if (token == null) {
            throw new LoginException("未登录，请登录！");
        }
        return checkToken(token, frontendType);
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        // 清理用户
        UserContext.removeContext();
    }


    private boolean checkToken(String token, String frontendType) {
        try {
            // 验证token
            Claims claims = JwtUtil.parseJWT(jwtProperties.getSecretKey(), token);
            // 从 claims 中获取用户ID
            Integer id = claims.get(frontendType + "Id", Integer.class);
            if (id == null) {
                log.error("Token中未包含用户ID");
                throw new LoginException("未登录，请登录！");
            }
            // 4. 从Redis中获取存储的Token
            String tokenRedis = stringRedisTemplate.opsForValue().get("login" + frontendType + ":" + id);
            if (tokenRedis == null) {
                log.error("用户的登录信息未在Redis中找到");
                throw new LoginException("登录已失效，请重新登录！");
            }

            // 5. 校验令牌是否一致
            if (!token.equals(tokenRedis)) {
                log.error("Token不一致，可能是重新登录");
                throw new LoginException("登录已失效，请重新登录！");
            }

            // 6. 存储用户信息
            UserContext.setContext(Long.valueOf(id), frontendType);
            // 7. 验证通过，允许请求继续
            return true;
        } catch (Exception e) {
            log.error("Token验证失败: ", e);
            throw new LoginException("登录已失效，请重新登录！");
        }
    }
}
